﻿/*************************************************************************
* @File			:	LuaManager.cs
* @Description	:
*
*
*
*
************************************************************************/

using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Threading;
using UnityEngine;
using XLua;

namespace Framework
{
    // -----------------------------------------------------------------------
    // @brief xlua 管理
    public class LuaManager : BaseManager<LuaManager>, IManager
    {
        // @brief xlua 环境
        private LuaEnv m_luaEnv;
        // @brief lua 加载
        private delegate byte[] LuaLoader(ref string filename);
        private LuaLoader m_luaLoader;
        // @brief xlua 字典存储ab包数据
        private Dictionary<string, byte[]> m_luaDict;
        // -----------------------------------------------------------------------
        // @brief 销毁
        public void Destroy()
        {
            if (m_luaDict != null)
            {
                m_luaDict.Clear();
                m_luaDict = null;
            }
            if (m_luaEnv == null) return;

            try
            {
                m_luaEnv.Dispose();
            }
            catch (Exception ex)
            {
#if UNITY_EDITOR
                Logger.LogError("[LogError] scripts env dispose is wrong: " + ex.ToString());
#else
                Logger.LogSys("scripts env dispose is wrong: " + ex.ToString());
#endif
            }
            m_luaEnv = null;
        }
        // -----------------------------------------------------------------------
        // @brief 初始化
        public void Init()
        {
            // lua加载选择
            m_luaLoader = LoadFromFile;
            // 新建lua环境
            m_luaEnv = new LuaEnv();
            // 给环境添加的一个加载
            m_luaEnv.AddLoader(CustomLoader);
        }
        // -----------------------------------------------------------------------
        // @brief 初始化
        public void NewUpdate()
        {
            if (m_luaEnv != null)
            {
                if (Time.time > nextUpdateTime)
                {
                    m_luaEnv.Tick();
                    nextUpdateTime = Time.time + updateInterval;
                }
            }
        }
        // -----------------------------------------------------------------------
        // @brief 重新开始
        public void Restart()
        {
            if (m_luaDict != null)
            {
                m_luaDict.Clear();
                m_luaDict = null;
            }
            // 新建lua环境
            m_luaEnv = new LuaEnv();
            // 给环境添加的一个加载
            m_luaEnv.AddLoader(CustomLoader);
        }
        // -----------------------------------------------------------------------
        // @brief 获取环境
        public LuaEnv GetEnv()
        {
            return m_luaEnv;
        }
        // -----------------------------------------------------------------------
        // @brief 获取lua文件路径
        // @param[fileName] 文件名字
        public string GetLuaFilePath(ref string fileName)
        {
            var path = "";
            var fileNameCopy = "";
            if (!fileName.EndsWith(".lua"))
            {
                fileName = fileName.Replace(".", "/");
                fileNameCopy = fileName + ".lua";
            }

            path = Path.Combine(Application.dataPath, "Scripts/LUA", fileNameCopy);
            return path;
        }
        // -----------------------------------------------------------------------
        // @brief 正常获取lua文件
        // @param[fileName] 文件名
        private byte[] LoadFromFile(ref string filename)
        {
            var path = GetLuaFilePath(ref filename);
            if (string.IsNullOrEmpty(path))
                return null;

            if (!File.Exists(path))
            {
                Logger.LogWarn(string.Format("can not found [%s]", path));
                return null;
            }

            var bytes = File.ReadAllBytes(path);
            long length = bytes.Length;

            return length <= 0 ? null : bytes;
        }
        // -----------------------------------------------------------------------
        // @brief 从AB包获取lua文件
        // @param[fileName] 文件名
        private byte[] LoadFromAB(ref string filename)
        {
            if (m_luaDict == null)
            {
                Logger.LogWarn("[XXXXX] scriptsDict fail!");
                return null;
            }

            var asName = filename;
            // 去掉.lua后缀
            var index = filename.IndexOf(".lua", StringComparison.Ordinal);
            if (index >= 0)
            {
                asName = filename.Substring(0, index);
            }

            index = asName.LastIndexOf(".", StringComparison.Ordinal);
            if (index >= 0)
            {
                asName = asName.Substring(index + 1);
            }

            asName = asName.ToLower();

            if (m_luaDict.TryGetValue(asName, out var text))
            {
                return text;
            }
            else
            {
                Logger.LogWarn("[XXXXX] load scripts text asset fail, asName is " + asName);
                return null;
            }
        }
        // -----------------------------------------------------------------------
        // @brief 从资源路径获取lua文件
        // @param[fileName] 文件名
        private byte[] LoadFromResource(ref string filename)
        {
            var text = Resources.Load<TextAsset>(filename);

            if (text != null)
            {
                return text.bytes;
            }
            else
            {
                Logger.LogWarn("[XXXXX] load scripts from Resources fail, filename is " + filename);
                return null;
            }
        }
        // -----------------------------------------------------------------------
        // @brief 用户读取xlua需要这东西
        // @param[fileName] 文件名
        private byte[] CustomLoader(ref string filename)
        {
            return m_luaLoader(ref filename);
        }
        // -----------------------------------------------------------------------
        // @brief 执行字符串Lua代码
        // @param[luaString] 内容
        public object[] DoString(string luaString)
        {
            return m_luaEnv.DoString(luaString);
        }
        // -----------------------------------------------------------------------
        // @brief 执行字符串Lua代码
        // @param[luaString] 内容
        public object[] DoString(string luaString, string chunkName)
        {
            
            return m_luaEnv.DoString(luaString, chunkName);
        }





        // -----------------------------------------------------------------------
        // @brief 执行Lua函数
        // @param[funcName] 函数名字
        // @param[args] 参数
        public void CallFunction(string funcName, params object[] args)
        {
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] is string) args[i] = "\"" + args[i] + "\"";
            }
            string luaString = string.Format("{0}({1})", funcName, string.Join(",", args));
            m_luaEnv.DoString(luaString);
        }
        // -----------------------------------------------------------------------
        // @brief 垃圾回收
        public void LuaGC()
        {
            m_luaEnv.GC();
        }
        // -----------------------------------------------------------------------
        // @brief 获取内存
        public float GetMemory()
        {
            return m_luaEnv.Memroy * 0.001f;
        }
        // -----------------------------------------------------------------------
        // @brief 全部回收
        public void FullGC()
        {
            m_luaEnv.FullGc();
        }
        // -----------------------------------------------------------------------
        // @brief 回收暂停
        public void StopGC()
        {
            m_luaEnv.StopGc();
        }
        // -----------------------------------------------------------------------
        // @brief 回收重启
        public void RestartGC()
        {
            m_luaEnv.RestartGc();
        }
        // -----------------------------------------------------------------------
        // @brief 关闭
        public void Close()
        {
            m_luaEnv.Dispose();
        }
    }
}
